home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / rpclib / xdr.c < prev   
C/C++ Source or Header  |  1994-03-09  |  12KB  |  587 lines

  1. /*
  2.  * $Id: xdr.c,v 1.4 1994/02/26 18:52:13 jraja Exp $
  3.  *
  4.  * $Log: xdr.c,v $
  5.  * Revision 1.4  1994/02/26  18:52:13  jraja
  6.  * Fixed some types.
  7.  *
  8.  * Revision 1.3  1993/11/14  23:35:09  jraja
  9.  * Removed LASTUNSIGNED definition.
  10.  *
  11.  * Revision 1.2  1993/11/14  16:41:38  jraja
  12.  * Fixed include. ANSI prototypes. Fixed types.
  13.  * Added XDRFUN to definitions of xdr functions.
  14.  * Changed LASTUNSIGNED to ANSI UINT_MAX.
  15.  *
  16.  */
  17. /* @(#)xdr.c    2.1 88/07/29 4.0 RPCSRC */
  18. /*
  19.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  20.  * unrestricted use provided that this legend is included on all tape
  21.  * media and as a part of the software program in whole or part.  Users
  22.  * may copy or modify Sun RPC without charge, but are not authorized
  23.  * to license or distribute it to anyone else except as part of a product or
  24.  * program developed by the user.
  25.  * 
  26.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  27.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  28.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  29.  * 
  30.  * Sun RPC is provided with no support and without any obligation on the
  31.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  32.  * modification or enhancement.
  33.  * 
  34.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  35.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  36.  * OR ANY PART THEREOF.
  37.  * 
  38.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  39.  * or profits or other special, indirect and consequential damages, even if
  40.  * Sun has been advised of the possibility of such damages.
  41.  * 
  42.  * Sun Microsystems, Inc.
  43.  * 2550 Garcia Avenue
  44.  * Mountain View, California  94043
  45.  */
  46. #if !defined(lint) && defined(SCCSIDS)
  47. static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
  48. #endif
  49.  
  50. /*
  51.  * xdr.c, Generic XDR routines implementation.
  52.  *
  53.  * Copyright (C) 1986, Sun Microsystems, Inc.
  54.  *
  55.  * These are the "generic" xdr routines used to serialize and de-serialize
  56.  * most common data items.  See xdr.h for more info on the interface to
  57.  * xdr.
  58.  */
  59.  
  60. #include <sys/param.h>
  61. #include <stdio.h>
  62. #include <rpc/types.h>
  63. #include <rpc/xdr.h>
  64.  
  65. #include <limits.h>
  66.  
  67. /*
  68.  * constants specific to the xdr "protocol"
  69.  */
  70. #define XDR_FALSE    ((long) 0)
  71. #define XDR_TRUE    ((long) 1)
  72.  
  73. /*
  74.  * for unit alignment
  75.  */
  76. static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
  77.  
  78. /*
  79.  * Free a data structure using XDR
  80.  * Not a filter, but a convenient utility nonetheless
  81.  */
  82. void
  83. xdr_free(xdrproc_t proc, void *objp)
  84. {
  85.     XDR x;
  86.     
  87.     x.x_op = XDR_FREE;
  88.     (*proc)(&x, objp);
  89. }
  90.  
  91. /*
  92.  * XDR nothing
  93.  */
  94. bool_t XDRFUN
  95. xdr_void(XDR * xdrs, void *dummy)
  96. {
  97.     return (TRUE);
  98. }
  99.  
  100. /*
  101.  * XDR integers
  102.  */
  103. bool_t XDRFUN
  104. xdr_int(xdrs, ip)
  105.     XDR *xdrs;
  106.     int *ip;
  107. {
  108.  
  109. #ifdef lint
  110.     (void) (xdr_short(xdrs, (short *)ip));
  111.     return (xdr_long(xdrs, (long *)ip));
  112. #else
  113.     if (sizeof (int) == sizeof (long)) {
  114.         return (xdr_long(xdrs, (long *)ip));
  115.     } else {
  116.         return (xdr_short(xdrs, (short *)ip));
  117.     }
  118. #endif
  119. }
  120.  
  121. /*
  122.  * XDR unsigned integers
  123.  */
  124. bool_t XDRFUN
  125. xdr_u_int(xdrs, up)
  126.     XDR *xdrs;
  127.     u_int *up;
  128. {
  129.  
  130. #ifdef lint
  131.     (void) (xdr_u_short(xdrs, (u_short *)up));
  132.     return (xdr_u_long(xdrs, (u_long *)up));
  133. #else
  134.     if (sizeof (u_int) == sizeof (u_long)) {
  135.         return (xdr_u_long(xdrs, (u_long *)up));
  136.     } else {
  137.         return (xdr_u_short(xdrs, (u_short *)up));
  138.     }
  139. #endif
  140. }
  141.  
  142. /*
  143.  * XDR long integers
  144.  * same as xdr_u_long - open coded to save a proc call!
  145.  */
  146. bool_t XDRFUN
  147. xdr_long(xdrs, lp)
  148.     register XDR *xdrs;
  149.     long *lp;
  150. {
  151.  
  152.     if (xdrs->x_op == XDR_ENCODE)
  153.         return (XDR_PUTLONG(xdrs, lp));
  154.  
  155.     if (xdrs->x_op == XDR_DECODE)
  156.         return (XDR_GETLONG(xdrs, lp));
  157.  
  158.     if (xdrs->x_op == XDR_FREE)
  159.         return (TRUE);
  160.  
  161.     return (FALSE);
  162. }
  163.  
  164. /*
  165.  * XDR unsigned long integers
  166.  * same as xdr_long - open coded to save a proc call!
  167.  */
  168. bool_t XDRFUN
  169. xdr_u_long(xdrs, ulp)
  170.     register XDR *xdrs;
  171.     u_long *ulp;
  172. {
  173.  
  174.     if (xdrs->x_op == XDR_DECODE)
  175.         return (XDR_GETLONG(xdrs, (long *)ulp));
  176.     if (xdrs->x_op == XDR_ENCODE)
  177.         return (XDR_PUTLONG(xdrs, (long *)ulp));
  178.     if (xdrs->x_op == XDR_FREE)
  179.         return (TRUE);
  180.     return (FALSE);
  181. }
  182.  
  183. /*
  184.  * XDR short integers
  185.  */
  186. bool_t XDRFUN
  187. xdr_short(xdrs, sp)
  188.     register XDR *xdrs;
  189.     short *sp;
  190. {
  191.     long l;
  192.  
  193.     switch (xdrs->x_op) {
  194.  
  195.     case XDR_ENCODE:
  196.         l = (long) *sp;
  197.         return (XDR_PUTLONG(xdrs, &l));
  198.  
  199.     case XDR_DECODE:
  200.         if (!XDR_GETLONG(xdrs, &l)) {
  201.             return (FALSE);
  202.         }
  203.         *sp = (short) l;
  204.         return (TRUE);
  205.  
  206.     case XDR_FREE:
  207.         return (TRUE);
  208.     }
  209.     return (FALSE);
  210. }
  211.  
  212. /*
  213.  * XDR unsigned short integers
  214.  */
  215. bool_t XDRFUN
  216. xdr_u_short(xdrs, usp)
  217.     register XDR *xdrs;
  218.     u_short *usp;
  219. {
  220.     u_long l;
  221.  
  222.     switch (xdrs->x_op) {
  223.  
  224.     case XDR_ENCODE:
  225.         l = (u_long) *usp;
  226.         return (XDR_PUTLONG(xdrs, (long *)&l));
  227.  
  228.     case XDR_DECODE:
  229.         if (!XDR_GETLONG(xdrs, (long *)&l)) {
  230.             return (FALSE);
  231.         }
  232.         *usp = (u_short) l;
  233.         return (TRUE);
  234.  
  235.     case XDR_FREE:
  236.         return (TRUE);
  237.     }
  238.     return (FALSE);
  239. }
  240.  
  241.  
  242. /*
  243.  * XDR a char
  244.  */
  245. bool_t XDRFUN
  246. xdr_char(xdrs, cp)
  247.     XDR *xdrs;
  248.     char *cp;
  249. {
  250.     int i;
  251.  
  252.     i = (*cp);
  253.     if (!xdr_int(xdrs, &i)) {
  254.         return (FALSE);
  255.     }
  256.     *cp = i;
  257.     return (TRUE);
  258. }
  259.  
  260. /*
  261.  * XDR an unsigned char
  262.  */
  263. bool_t XDRFUN
  264. xdr_u_char(xdrs, cp)
  265.     XDR *xdrs;
  266.     u_char *cp;
  267. {
  268.     u_int u;
  269.  
  270.     u = (*cp);
  271.     if (!xdr_u_int(xdrs, &u)) {
  272.         return (FALSE);
  273.     }
  274.     *cp = u;
  275.     return (TRUE);
  276. }
  277.  
  278. /*
  279.  * XDR booleans
  280.  */
  281. bool_t XDRFUN
  282. xdr_bool(xdrs, bp)
  283.     register XDR *xdrs;
  284.     bool_t *bp;
  285. {
  286.     long lb;
  287.  
  288.     switch (xdrs->x_op) {
  289.  
  290.     case XDR_ENCODE:
  291.         lb = *bp ? XDR_TRUE : XDR_FALSE;
  292.         return (XDR_PUTLONG(xdrs, &lb));
  293.  
  294.     case XDR_DECODE:
  295.         if (!XDR_GETLONG(xdrs, &lb)) {
  296.             return (FALSE);
  297.         }
  298.         *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
  299.         return (TRUE);
  300.  
  301.     case XDR_FREE:
  302.         return (TRUE);
  303.     }
  304.     return (FALSE);
  305. }
  306.  
  307. /*
  308.  * XDR enumerations
  309.  */
  310. bool_t XDRFUN
  311. xdr_enum(xdrs, ep)
  312.     XDR *xdrs;
  313.     enum_t *ep;
  314. {
  315. #ifndef lint
  316.     enum sizecheck { SIZEVAL };    /* used to find the size of an enum */
  317.  
  318.     /*
  319.      * enums are treated as ints
  320.      */
  321.     if (sizeof (enum sizecheck) == sizeof (long)) {
  322.         return (xdr_long(xdrs, (long *)ep));
  323.     } else if (sizeof (enum sizecheck) == sizeof (short)) {
  324.         return (xdr_short(xdrs, (short *)ep));
  325.     } else {
  326.         return (FALSE);
  327.     }
  328. #else
  329.     (void) (xdr_short(xdrs, (short *)ep));
  330.     return (xdr_long(xdrs, (long *)ep));
  331. #endif
  332. }
  333.  
  334. /*
  335.  * XDR opaque data
  336.  * Allows the specification of a fixed size sequence of opaque bytes.
  337.  * cp points to the opaque object and cnt gives the byte length.
  338.  */
  339. bool_t XDRFUN
  340. xdr_opaque(xdrs, cp, cnt)
  341.     register XDR *xdrs;
  342.     caddr_t cp;
  343.     register u_int cnt;
  344. {
  345.     register u_int rndup;
  346.     static char crud[BYTES_PER_XDR_UNIT];
  347.  
  348.     /*
  349.      * if no data we are done
  350.      */
  351.     if (cnt == 0)
  352.         return (TRUE);
  353.  
  354.     /*
  355.      * round byte count to full xdr units
  356.      */
  357.     rndup = cnt % BYTES_PER_XDR_UNIT;
  358.     if (rndup > 0)
  359.         rndup = BYTES_PER_XDR_UNIT - rndup;
  360.  
  361.     if (xdrs->x_op == XDR_DECODE) {
  362.         if (!XDR_GETBYTES(xdrs, cp, cnt)) {
  363.             return (FALSE);
  364.         }
  365.         if (rndup == 0)
  366.             return (TRUE);
  367.         return (XDR_GETBYTES(xdrs, crud, rndup));
  368.     }
  369.  
  370.     if (xdrs->x_op == XDR_ENCODE) {
  371.         if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
  372.             return (FALSE);
  373.         }
  374.         if (rndup == 0)
  375.             return (TRUE);
  376.         return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
  377.     }
  378.  
  379.     if (xdrs->x_op == XDR_FREE) {
  380.         return (TRUE);
  381.     }
  382.  
  383.     return (FALSE);
  384. }
  385.  
  386. /*
  387.  * XDR counted bytes
  388.  * *cpp is a pointer to the bytes, *sizep is the count.
  389.  * If *cpp is NULL maxsize bytes are allocated
  390.  */
  391. bool_t XDRFUN
  392. xdr_bytes(xdrs, cpp, sizep, maxsize)
  393.     register XDR *xdrs;
  394.     char **cpp;
  395.     register u_int *sizep;
  396.     u_int maxsize;
  397. {
  398.     register char *sp = *cpp;  /* sp is the actual string pointer */
  399.     register u_int nodesize;
  400.  
  401.     /*
  402.      * first deal with the length since xdr bytes are counted
  403.      */
  404.     if (! xdr_u_int(xdrs, sizep)) {
  405.         return (FALSE);
  406.     }
  407.     nodesize = *sizep;
  408.     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
  409.         return (FALSE);
  410.     }
  411.  
  412.     /*
  413.      * now deal with the actual bytes
  414.      */
  415.     switch (xdrs->x_op) {
  416.  
  417.     case XDR_DECODE:
  418.         if (nodesize == 0) {
  419.             return (TRUE);
  420.         }
  421.         if (sp == NULL) {
  422.             *cpp = sp = (char *)mem_alloc(nodesize);
  423.         }
  424.         if (sp == NULL) {
  425.             (void) fprintf(stderr, "xdr_bytes: out of memory\n");
  426.             return (FALSE);
  427.         }
  428.         /* fall into ... */
  429.  
  430.     case XDR_ENCODE:
  431.         return (xdr_opaque(xdrs, sp, nodesize));
  432.  
  433.     case XDR_FREE:
  434.         if (sp != NULL) {
  435.             mem_free(sp, nodesize);
  436.             *cpp = NULL;
  437.         }
  438.         return (TRUE);
  439.     }
  440.     return (FALSE);
  441. }
  442.  
  443. /*
  444.  * Implemented here due to commonality of the object.
  445.  */
  446. bool_t XDRFUN
  447. xdr_netobj(xdrs, np)
  448.     XDR *xdrs;
  449.     struct netobj *np;
  450. {
  451.  
  452.     return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
  453. }
  454.  
  455. /*
  456.  * XDR a descriminated union
  457.  * Support routine for discriminated unions.
  458.  * You create an array of xdrdiscrim structures, terminated with
  459.  * an entry with a null procedure pointer.  The routine gets
  460.  * the discriminant value and then searches the array of xdrdiscrims
  461.  * looking for that value.  It calls the procedure given in the xdrdiscrim
  462.  * to handle the discriminant.  If there is no specific routine a default
  463.  * routine may be called.
  464.  * If there is no specific or default routine an error is returned.
  465.  */
  466. bool_t XDRFUN
  467. xdr_union(xdrs, dscmp, unp, choices, dfault)
  468.     register XDR *xdrs;
  469.     enum_t *dscmp;        /* enum to decide which arm to work on */
  470.     char *unp;        /* the union itself */
  471.     struct xdr_discrim *choices;    /* [value, xdr proc] for each arm */
  472.     xdrproc_t dfault;    /* default xdr routine */
  473. {
  474.     register enum_t dscm;
  475.  
  476.     /*
  477.      * we deal with the discriminator;  it's an enum
  478.      */
  479.     if (! xdr_enum(xdrs, dscmp)) {
  480.         return (FALSE);
  481.     }
  482.     dscm = *dscmp;
  483.  
  484.     /*
  485.      * search choices for a value that matches the discriminator.
  486.      * if we find one, execute the xdr routine for that value.
  487.      */
  488.     for (; choices->proc != NULL_xdrproc_t; choices++) {
  489.         if (choices->value == dscm)
  490.             return ((*(xdr_string_t)(choices->proc))(xdrs, unp,
  491.                                  UINT_MAX));
  492.     }
  493.  
  494.     /*
  495.      * no match - execute the default xdr routine if there is one
  496.      */
  497.     return ((dfault == NULL_xdrproc_t) ? FALSE :
  498.         (*(xdr_string_t)dfault)(xdrs, unp, UINT_MAX));
  499. }
  500.  
  501.  
  502. /*
  503.  * Non-portable xdr primitives.
  504.  * Care should be taken when moving these routines to new architectures.
  505.  */
  506.  
  507.  
  508. /*
  509.  * XDR null terminated ASCII strings
  510.  * xdr_string deals with "C strings" - arrays of bytes that are
  511.  * terminated by a NULL character.  The parameter cpp references a
  512.  * pointer to storage; If the pointer is null, then the necessary
  513.  * storage is allocated.  The last parameter is the max allowed length
  514.  * of the string as specified by a protocol.
  515.  */
  516. bool_t XDRFUN
  517. xdr_string(xdrs, cpp, maxsize)
  518.     register XDR *xdrs;
  519.     char **cpp;
  520.     u_int maxsize;
  521. {
  522.     register char *sp = *cpp;  /* sp is the actual string pointer */
  523.     u_int size;
  524.     u_int nodesize;
  525.  
  526.     /*
  527.      * first deal with the length since xdr strings are counted-strings
  528.      */
  529.     switch (xdrs->x_op) {
  530.     case XDR_FREE:
  531.         if (sp == NULL) {
  532.             return(TRUE);    /* already free */
  533.         }
  534.         /* fall through... */
  535.     case XDR_ENCODE:
  536.         size = strlen(sp);
  537.         break;
  538.     }
  539.     if (! xdr_u_int(xdrs, &size)) {
  540.         return (FALSE);
  541.     }
  542.     if (size > maxsize) {
  543.         return (FALSE);
  544.     }
  545.     nodesize = size + 1;
  546.  
  547.     /*
  548.      * now deal with the actual bytes
  549.      */
  550.     switch (xdrs->x_op) {
  551.  
  552.     case XDR_DECODE:
  553.         if (nodesize == 0) {
  554.             return (TRUE);
  555.         }
  556.         if (sp == NULL)
  557.             *cpp = sp = (char *)mem_alloc(nodesize);
  558.         if (sp == NULL) {
  559.             (void) fprintf(stderr, "xdr_string: out of memory\n");
  560.             return (FALSE);
  561.         }
  562.         sp[size] = 0;
  563.         /* fall into ... */
  564.  
  565.     case XDR_ENCODE:
  566.         return (xdr_opaque(xdrs, sp, size));
  567.  
  568.     case XDR_FREE:
  569.         mem_free(sp, nodesize);
  570.         *cpp = NULL;
  571.         return (TRUE);
  572.     }
  573.     return (FALSE);
  574. }
  575.  
  576. /* 
  577.  * Wrapper for xdr_string that can be called directly from 
  578.  * routines like clnt_call
  579.  */
  580. bool_t XDRFUN
  581. xdr_wrapstring(xdrs, cpp)
  582.     XDR *xdrs;
  583.     char **cpp;
  584. {
  585.     return xdr_string(xdrs, cpp, UINT_MAX);
  586. }
  587.